# Лекция: Factory Pattern в Java

Factory (фабрика) - это порождающий шаблон проектирования, который предоставляет интерфейс для создания объектов в суперклассе, но позволяет подклассам изменять тип создаваемых объектов.

## Пример использования Factory Pattern

```java
public abstract class Animal {
    public abstract String makeSound();
}

public class Dog extends Animal {
    public String makeSound() {
        return "Woof";
    }
}

public class Cat extends Animal {
    public String makeSound() {
        return "Meow";
    }
}

public class AnimalFactory {
    public Animal getAnimal(String type) {
        if ("Dog".equalsIgnoreCase(type)) {
            return new Dog();
        } else if ("Cat".equalsIgnoreCase(type)) {
            return new Cat();
        }
        return null;
    }
}
```

В этом примере `AnimalFactory` создает объекты `Dog` или `Cat` в зависимости от переданного типа.

## Использование Factory класса

```java
AnimalFactory animalFactory = new AnimalFactory();

Animal dog = animalFactory.getAnimal("Dog");
System.out.println(dog.makeSound()); // выводит "Woof"

Animal cat = animalFactory.getAnimal("Cat");
System.out.println(cat.makeSound()); // выводит "Meow"
```

В этом примере `AnimalFactory` используется для создания объектов `Dog` и `Cat`.

---

# Практические задания

1. **Создайте классы `Shape`, `Circle` и `Square` и класс `ShapeFactory`, который создает объекты `Circle` или `Square` в зависимости от переданного типа.** (Сложность: 2/5)
```java
public interface Shape {
    void draw();
}

public class Circle implements Shape {
    public void draw() {
        System.out.println("Drawing a circle");
    }
}

public class Square implements Shape {
    public void draw() {
        System.out.println("Drawing a square");
    }
}

public class ShapeFactory {
    public Shape getShape(String shapeType) {
        if ("CIRCLE".equalsIgnoreCase(shapeType)) {
            return new Circle();
        } else if ("SQUARE".equalsIgnoreCase(shapeType)) {
            return new Square();
        }
        return null;
    }
}
```

2. **Используйте `ShapeFactory` для создания объектов `Circle` и `Square` и вызова их методов `draw`.** (Сложность: 1/5)
```java
ShapeFactory shapeFactory = new ShapeFactory();

Shape circle = shapeFactory.getShape("CIRCLE");
circle.draw(); // выводит "Drawing a circle"

Shape square = shapeFactory.getShape("SQUARE");
square.draw(); // выводит "Drawing a square"
```

3. **Добавьте в `ShapeFactory` поддержку создания объектов `Rectangle`.** (Сложность: 2/5)
```java
public class Rectangle implements Shape {
    public void draw() {
        System.out.println("Drawing a rectangle");
    }
}

public class ShapeFactory {
    public Shape getShape(String shapeType) {
        if ("CIRCLE".equalsIgnoreCase(shapeType)) {
            return new Circle();
        } else if ("SQUARE".equalsIgnoreCase(shapeType)) {
            return new Square();
        } else if ("RECTANGLE".equalsIgnoreCase(shapeType)) {
            return new Rectangle();
        }
        return null;
    }
}
```

4. **Используйте `ShapeFactory` для создания объекта `Rectangle` и вызова его метода `draw`.** (Сложность: 1/5)
```java
ShapeFactory shapeFactory = new ShapeFactory();

Shape rectangle = shapeFactory.getShape("RECTANGLE");
rectangle.draw(); // выводит "Drawing a rectangle"
```

5. **Создайте класс `ShapeFactoryTest`, который тестирует `ShapeFactory` с использованием JUnit и Mockito.** (Сложность: 4/5)
```java
import static org.junit.Assert.*;
import static org.mockito.Mockito.*;

public class ShapeFactoryTest {
    @Test
    public void testGetShape() {
        ShapeFactory shapeFactory = new ShapeFactory();

        Shape circle = shapeFactory.getShape("CIRCLE");
        assertTrue(circle instanceof Circle);

        Shape square = shapeFactory.getShape("SQUARE");
        assertTrue(square instanceof Square);

        Shape rectangle = shapeFactory.getShape("RECTANGLE");
        assertTrue(rectangle instanceof Rectangle);
    }
}
```